package com.lw.shiro.config;

import com.lw.shiro.realm.HrmRealm;
import com.lw.shiro.realm.UserRealm;
import com.lw.shiro.session.CustomSessionManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Value( "${spring.redis.host}" )
    private String host;
    @Value( "${spring.redis.port}" )
    private int port;
    // 下面方法对 注解权限起作用有很大的关系，请把这两个方法，放在配置的最上面

//    @Bean
//    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
//        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
//        autoProxyCreator.setProxyTargetClass( true );
//        return autoProxyCreator;
//    }
        //1.创建 realm
    @Bean
    public HrmRealm getRealm(){
        return new UserRealm();
    }
    //2.创建 安全管理器
    @Bean
    public SecurityManager securityManager(@Autowired HrmRealm realm){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        securityManager.setRealm( realm );
//        //将自定义的会话管理器注册到安全管理器中
        securityManager.setSessionManager( sessionManager() );
//        //将自定义缓存管理器注册到安全管理器
        securityManager.setCacheManager( cacheManager() );
        return securityManager;
    }
    //配置注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Autowired SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
    //3.配置 shiro的过滤器工厂

    /**
     *在web程序中，shiro进行权限控制都是通过一组过滤器集合进行控制
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(@Autowired SecurityManager securityManager){
        //1.创建过滤器工厂
        ShiroFilterFactoryBean filterFactory=new ShiroFilterFactoryBean();
        //2.设置安全管理器
        filterFactory.setSecurityManager( securityManager );
        //3.通用配置（跳转登陆页面，为授权跳转的页面）
        filterFactory.setLoginUrl( "/autherror?code=1" );//未登录跳转url地址
        filterFactory.setUnauthorizedUrl( "/autherror?code=2" );//未授权的url
//        //4.设置过滤集合 有顺序的map
        Map<String,String> filterMap=new LinkedHashMap<>();
        filterMap.put( "/user/faceLogin/**","anon" );//用于人脸登录
        filterMap.put( "/autherror","anon" ); //请求地址可以匿名访问
        filterMap.put( "/user/login","anon" ); //请求地址可以匿名访问
        filterMap.put( "/user/**","authc" );//请求地址必须登录才能访问
        filterFactory.setFilterChainDefinitionMap( filterMap );
        return filterFactory;
    }
    //会话管理配置开始
    //1.redis的控制器，操作redis
    public RedisManager redisManager(){
        RedisManager redisManager=new RedisManager();
        redisManager.setHost( host );
        redisManager.setPort( port );
        return redisManager;
    }
    //2.sessionDao
    public RedisSessionDAO redisSessionDAO(){
        RedisSessionDAO redisSessionDAO=new RedisSessionDAO();
        redisSessionDAO.setRedisManager( redisManager() );
        return redisSessionDAO;
    }
    //3.会话管理器器
    public DefaultWebSessionManager sessionManager(){
        CustomSessionManager sessionManager=new CustomSessionManager();
        sessionManager.setSessionDAO( redisSessionDAO() );
//        //禁用cookie
        sessionManager.setSessionIdCookieEnabled( false );
        //禁用url重写
        sessionManager.setSessionIdUrlRewritingEnabled( false );
        return sessionManager;
    }
    //4.缓存管理器
    public RedisCacheManager cacheManager(){
        RedisCacheManager cacheManager=new RedisCacheManager();
        cacheManager.setRedisManager( redisManager() );
        return cacheManager;
    }
    //会话管理配置结束
}
